/**
  在 React 中，组件可以分为两种类型：受控组件（Controlled Components）和非受控组件（Uncontrolled Components）。它们在状态管理和数据流动方面有着不同的特点。
  1. 受控组件（Controlled Components）
  受控组件是指其值由 React 组件的 state 控制的组件。所有的表单数据都由组件的 state 管理，用户输入的值会通过  `onChange`  事件更新 state，从而实现数据的单向流动。
   示例：
  jsx
  class ControlledComponent extends React.Component {
    constructor(props) {
      super(props);
      this.state = { value: '' };
    }

    handleChange = (event) => {
      this.setState({ value: event.target.value });
    };

    render() {
      return (
        <input
          type="text"
          value={this.state.value} // 受控
          onChange={this.handleChange} // 更新 state
        />
      );
    }
  }
   特点：
  - 单向数据流：数据从父组件流向子组件，用户输入的值通过事件回调更新组件的 state。
  - 更易于控制：可以在输入时进行验证、格式化或其他处理。
  - 状态集中管理：所有表单状态都在 React 的 state 中，便于管理和调试。

  2. 非受控组件（Uncontrolled Components）
  非受控组件是指其值不由 React 组件的 state 管理，而是直接由 DOM 元素的状态控制。可以通过  `ref`  来访问 DOM 元素的值。
   示例：
  jsx
  class UncontrolledComponent extends React.Component {
    constructor(props) {
      super(props);
      this.inputRef = React.createRef(); // 创建 ref
    }

    handleSubmit = (event) => {
      event.preventDefault();
      alert('A name was submitted: ' + this.inputRef.current.value); // 访问 DOM 元素的值
    };
    render() {
      return (
        <form onSubmit={this.handleSubmit}>
          <input type="text" ref={this.inputRef} /> 非受控 
          <button type="submit">Submit</button>
        </form>
      );
    }
  }
   特点：
  - 直接访问 DOM：通过  `ref`  可以直接获取 DOM 元素的值，而不需要通过 state。
  - 灵活性：适用于不需要实时更新状态的场景，比如文件上传或简单的表单提交。
  - 较少的代码：在简单场景下，非受控组件的实现可能更简洁。

  3. 总结

  - 受控组件：由 React 的 state 管理，适合需要实时反馈和复杂验证的场景，数据流动清晰，易于管理。
  - 非受控组件：直接依赖 DOM 元素的状态，适合简单的表单处理，减少了 React 的状态管理负担。

  选择使用受控组件还是非受控组件，通常取决于具体的应用场景和需求。在需要复杂状态管理和实时反馈的情况下，受控组件更为合适；而在简单场景下，非受控组件可能更加方便。
 */
import React, { PureComponent, createRef } from 'react'

export default class App extends PureComponent {
  constructor() {
    super()
    this.state = {
      username: 'Controlled components',
      password: "",
      isAgree: false,
      hobbies: [
        { value: "sing", text: "唱", isChecked: false },
        { value: "dance", text: "跳", isChecked: false },
        { value: "rap", text: "rap", isChecked: false }
      ],
      fruit: ["orange"],
      intro: "Controlled"
    }
    this.introRef = createRef()
  }
  
  handleInputChange(event) {
    console.log('input发生了改变', event.target.value)
    this.setState({ [event.target.name]: event.target.value })
  }

  handleAgreeChange(event) {
    console.log('checkbox发生了改变', event.target.checked)
    this.setState({ isAgree: event.target.checked })
  }

  handleHobbiesChange(event, index) {
    console.log('checkbox发生了改变', event.target.checked)
    const hobbies = [...this.state.hobbies]
    hobbies[index].isChecked = event.target.checked
    this.setState({ hobbies })
  }

  handleFruitChange(event) {
    const options = Array.from(event.target.selectedOptions)
    const fruit = options.map(item => item.value)
    this.setState({ fruit })

    // 额外补充: Array.from(可迭代对象)
    // Array.from(arguments)
    const value = Array.from(event.target.selectedOptions, item => item.value)
    console.log(value)
  }

  handleSubmit(event) {
    event.preventDefault()

    // 2.获取到所有的表单数据, 对数据进行组件
    console.log("获取所有的输入内容")
    console.log(this.state.username, this.state.password)
    const hobbies = this.state.hobbies.filter(item => item.isChecked).map(item => item.value)
    console.log("获取爱好: ", hobbies)
    console.log("获取结果:", this.introRef.current.value)
  }
  
  render() {
    const { username, password, isAgree, hobbies, fruit, intro} = this.state
    
    return (
      <div>
        <h3>1. 受控组件(Controlled components)</h3>
        <input type="checkbox" value={username} onChange={e => this.handleInputChange(e)} />

        <h3>2. 非受控组件(Uncontrolled components)</h3>
        <input type="text" />
        <h4>username: {username}</h4>

        <h2>3. 受控组件和非受控组件案例</h2>
        <form onSubmit={e => this.handleSubmit(e)}>
          {/* 1.用户名和密码 */}
          <label htmlFor="username">用户名：</label>
          <input
           type="text"
           id="username" 
           name="username" 
           value={username}
           onChange={e => this.handleInputChange(e)}
          />
          <br />
          <label htmlFor="password">密码：</label>
          <input
           type="password"
           id="password" 
           name="password" 
           value={password}
           onChange={e => this.handleInputChange(e)}
          />
          <br />

          {/* 2.checkbox单选 */}
          <label htmlFor="agree">同意协议</label>
          <input
           type="checkbox"
           id="agree" 
           name="agree" 
           checked={isAgree}
           onChange={e => this.handleAgreeChange(e)}
          />
          <br />

          {/* 3.checkbox多选 */}
          <div>
            您的爱好:
            {
              hobbies.map((item, index) => {
                return (
                  <label htmlFor={item.value} key={index}>
                    <input
                      type="checkbox"
                      name={item.value}
                      checked={item.checked}
                      onChange={e => this.handleHobbiesChange(e, index)}
                    />
                    <span>{item.title}</span>
                  </label>
                )
              })
            }
          </div>

          {/* 4. select */}
          <select value={fruit} onChange={e => this.handleFruitChange(e)} multiple>
            <option value="apple">苹果</option>
            <option value="orange">橘子</option>
            <option value="banana">香蕉</option>
          </select>
          <br />

          {/* 5. 非受控组件, defaultValue */}
          <input type="text" defaultValue={intro} ref={this.introRef} />

          <div>
            <button type='submit'>注册</button>
          </div>
        
        </form>
        
      </div>
    )
  }
}
